package cn.anecansaitin.whimsy.common.capabilities.battle;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.neoforge.common.util.INBTSerializable;
import org.jetbrains.annotations.UnknownNullability;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

public class BattleMode implements IBattleMode, INBTSerializable<CompoundTag> {
    private static final Map<String, Supplier<IBattleController>> BATTLE_CONTROLLERS = new HashMap<>();
    private boolean isInMode = false;
    private boolean isDirt = false;
    private IBattleController battleController;

    @Override
    public boolean isInMode() {
        return isInMode;
    }

    @Override
    public void setMode(boolean battleMode) {
        isInMode = battleMode;
        setDirt();
    }

    @Override
    public void switchMode(LivingEntity entity) {
        if (isInMode) {
            getController().onQuitedMode(entity);
        }

        isInMode = !isInMode;
        setDirt();
    }

    @Override
    public IBattleController getController() {
        return battleController;
    }

    @Override
    public void setController(IBattleController controller) {
        battleController = controller;
    }

    @Override
    public void setController(String controllerId) {
        if (battleController == null || !battleController.getId().equals(controllerId)) {
            battleController = BATTLE_CONTROLLERS.get(controllerId).get();
        }
    }

    @Override
    public void tick(LivingEntity entity) {
        if (isInMode()) {
            getController().tick(entity);
            setDirt();
        }
    }

    private void setDirt() {
        isDirt = true;
    }

    public void setClean() {
        isDirt = false;
    }

    public boolean isDirt() {
        return isDirt;
    }

    @Override
    public CompoundTag serializeNBT() {
        CompoundTag tag = new CompoundTag();
        tag.putBoolean("is_in_mode", isInMode());

        if (!isInMode() || getController() == null) {
            return tag;
        }

        CompoundTag controller = new CompoundTag();
        tag.put("controller", controller);
        controller.putString("id", getController().getId());
        controller.put("controller", getController().serializeNBT());
        return tag;
    }

    @Override
    public void deserializeNBT(CompoundTag nbt) {
        isInMode = nbt.getBoolean("is_in_mode");

        if (!nbt.contains("controller")) {
            return;
        }

        CompoundTag controller = nbt.getCompound("controller");
        String id = controller.getString("id");

        if (getController() == null || getController().getId().equals(id)) {
            getController().deserializeNBT(controller.getCompound("controller"));
        } else {
            battleController = BATTLE_CONTROLLERS.get(id).get();
        }
    }

    /**
     * 在Mod初始化时调用
     * @param id 控制器ID
     * @param supplier 控制器供应
     */
    public static void registerBattleController(String id, Supplier<IBattleController> supplier) {
        BATTLE_CONTROLLERS.put(id, supplier);
    }
}
